home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
DECL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
20KB
|
609 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
#define GEN
#include "hdr.h"
#include "vars.h"
#include "gvars.h"
#include "ops.h"
#include "setp.h"
#include "maincasp.h"
#include "miscp.h"
#include "smiscp.h"
#include "segment.h"
#include "genp.h"
#include "typep.h"
#include "statp.h"
#include "segmentp.h"
#include "exprp.h"
#include "gmiscp.h"
#include "gutilp.h"
#include "axqrp.h"
#include "declp.h"
static void gen_structured_object(Node, Symbol, int);
void create_object(Tuple id_list_arg, Symbol type_name, Node init_node,
int obj_is_constant) /*;create_object*/
{
/*
* This procedure is used to create objects (const or var).
* id_list is a list (tuple) of name nodes of objects to be created.
* The initialization part cannot have side effect, unless id_list
* contains a single element (transformation by expander)
*
* In order to generate not too bad a code, this procedure is organized
* as a gigantic if ... elseif ... elseif... structure, checking for the
* different configurations. Optimizations may still be added.
*
* The following cases are considered:
*
* 1/ Size of object and initial value are known statically.
* a/ Global object or local constant (promoted to global)
* with static initial value.
* b/ Global object initialized with dynamic value.
* Static part is initialized in data segment.
* c/ Uninitialized global object (variable or deferred
* constant).
* d/ Local constant initialized with dynamic value,
* deferred constant, or local variable.
*
* 2/ Size of object is not known statically
* a/ Global object with variable size (transformed into
* renaming).
* b/ Local array or record with variable size.
*
*/
Node node, id, first_id, last_id, init_call_node, pre_node;
Symbol first_name, obj_name;
int obj_is_global, ikind, i, n;
Fortup ft1;
Segment init_val; /* type should be Ivalue */
Node dyn_node;
Symbol model_name, subtype;
Tuple tup, id_list;
Const ival, small_const;
int special_aggregate;
/* id_list_arg needed since id_list used desctructively 6-25-85 */
id_list = tup_copy(id_list_arg);
#ifdef TRACE
if (debug_flag) {
/*gen_trace("CREATE_OBJECT", id_list);*/
gen_trace("CREATE_OBJECT");
FORTUP(node = (Node), id_list, ft1);
gen_trace_node(" CREATE_OBJECT argument", node);
ENDFORTUP(ft1);
}
#endif
init_val = (Segment)0; /* indicate not yet defined */
obj_is_global = CURRENT_LEVEL == 1;
if (N_KIND(init_node) == as_init_call) {
/* Initialization procedure call */
init_call_node = init_node;
init_node = OPT_NODE;
}
else {
init_call_node = OPT_NODE;
}
while (N_KIND(init_node) == as_insert) {
FORTUP(pre_node = (Node), N_LIST(init_node), ft1);
compile(pre_node);
ENDFORTUP(ft1);
init_node = N_AST1(init_node);
}
if (N_KIND(init_node) == as_raise) {
/* Simplest case, indeed. */
compile(init_node);
init_node = OPT_NODE;
}
if (has_static_size(type_name) && !(is_array_type(type_name)
&&is_unconstrained(type_name))
&& (init_node == OPT_NODE ||has_static_size(get_type(init_node)))) {
/*
* 1- Size of object is known statically(and also size of initial value)
* -------------------------------------
*/
if ((obj_is_global || obj_is_constant) && is_ivalue(init_node)) {
/*
* 1a- Global object or local const (promoted to global)
* with static initial value.
* Generate objects in data seg initialized with value
* Generate only one object for multiple constants.
*/
if (is_fixed_type(type_name)) {
init_val = segment_new(SEGMENT_KIND_DATA, 1);
small_const = small_of(base_type(type_name));
segment_put_long(init_val , rat_tof(get_ivalue(init_node),
small_const, size_of(type_name) ));
}
else if (is_simple_type(type_name)) {
ival = get_ivalue(init_node);
ikind = ival->const_kind;
if(ikind == CONST_INT) {
init_val = segment_new(SEGMENT_KIND_DATA, 1);
segment_put_word(init_val, ival->const_value.const_int);
}
else if(ikind == CONST_REAL) {
init_val = segment_new(SEGMENT_KIND_DATA, 1);
segment_put_real(init_val, ival->const_value.const_real);
}
else {
#ifdef DEBUG
printf("const_kind %d\n", ikind);
#endif
chaos("create_object:unsupported kind");
}
}
else if (is_array_type(type_name)) {
/* build the appropriate vector... */
init_val = array_ivalue(init_node);
}
else if (is_record_type(type_name)) {
init_val = record_ivalue(init_node);
}
else {
compiler_error_k("Unknown type for constant ", init_node);
return;
}
if (obj_is_constant) {
first_name = get_constant_name(init_val);
FORTUP(id = (Node), id_list, ft1);
obj_name = N_UNQ(id);
assign_same_reference(obj_name, first_name);
ENDFORTUP(ft1);
}
else {
FORTUP(id = (Node), id_list, ft1);
obj_name = N_UNQ(id);
next_global_reference_segment(obj_name, init_val);
ENDFORTUP(ft1);
}
}
else if (obj_is_global && init_node != OPT_NODE) {
/*
* 1b- Global object initialized with dynamic value
* Generate first object in data seg with static part
* initialized, compile code to initialize the rest,
* then assign first object to others
*/
if (N_KIND(init_node) == as_array_aggregate) {
init_val = array_ivalue(init_node);
}
else if (N_KIND(init_node) == as_record_aggregate) {
init_val = record_ivalue(init_node);
}
else {
/* TBSL: review translation from SETL */
/* build segment of desired length, initially all zero */
n = size_of(type_name);
init_val = segment_new(SEGMENT_KIND_DATA, n);
for (i = 1; i <= n; i++) {
segment_put_word(init_val, 0);
}
}
FORTUP(id = (Node), id_list, ft1);
obj_name = N_UNQ(id);
next_global_reference_segment(obj_name, init_val);
ENDFORTUP(ft1);
if (is_simple_type(type_name)) {
gen_value(init_node);
last_id = (Node) tup_frome(id_list);
FORTUP(id = (Node), id_list, ft1);
id = (Node) tup_fromb(id_list);
obj_name = (Symbol) N_UNQ(id);
gen_k(I_DUPLICATE, kind_of(type_name));
gen_ks(I_POP, kind_of(type_name), obj_name);
ENDFORTUP(ft1);
obj_name = N_UNQ(last_id);
gen_ks(I_POP, kind_of(type_name), obj_name);
}
else {
first_id = (Node) tup_fromb(id_list);
if (is_aggregate(init_node)) {
init_node = N_AST2(N_AST1(init_node));
compile(init_node);
}
else {
select_assign(first_id, init_node, type_name);
}
FORTUP(id = (Node), id_list, ft1);
select_assign(id, first_id, type_name);
ENDFORTUP(ft1);
}
}
else if (obj_is_global) {
/*
* 1c- Uninitialized global object (Variable or deferred
* constant)
* Generate objects in data segment. If initialization
* procedure, call it on first object, then assign first
* object to others.
*/
/* build a segment, initially all zeros, of desired length */
n = size_of(type_name);
/*
* this is a kludge for deferred const EMPTY in VAR_STRING package.
*/
if (n== 0) n = 3;
init_val = segment_new(SEGMENT_KIND_DATA, n);
for (i = 1; i <= n; i++)
segment_put_word(init_val, 0);
FORTUP(id = (Node), id_list, ft1);
obj_name = N_UNQ(id);
next_global_reference_segment(obj_name, init_val);
ENDFORTUP(ft1);
if (init_call_node != OPT_NODE ) {
compile(init_call_node); /* This initializes 1st object */
first_id = (Node) tup_fromb(id_list);
FORTUP(id = (Node), id_list, ft1); /* Assign it to other objs */
select_assign(id, first_id, type_name);
ENDFORTUP(ft1);
}
}
else {
/*
* 1d- Local constant initialized with dynamic val